`timescale 1ns / 1ps
// n4fpga.v - Top level module for the ECE 544 Project 1
//
// Copyright Roy Kravitz, Portland State University 2013, 2014, 2015
//
// Created By:	Roy Kravitz
// Date:		31-December-2014
// Version:		1.0
// Modified By: Abhishek Malik
// Date:		26-January-2014
// Description:
// ------------
// This module provides the top level for the Getting Started hardware.
// The module assume that a PmodCLP is plugged into the JA and JB
// expansion ports and that a PmodENC is plugged into the JD expansion 
// port (bottom row).  
//////////////////////////////////////////////////////////////////////
module n4fpga(
    input				clk,			// 100Mhz clock input
    input				btnC,			// center pushbutton
    input				btnU,			// UP (North) pusbhbutton
    input				btnL,			// LEFT (West) pushbutton
    input				btnD,			// DOWN (South) pushbutton  - used for system reset
    input				btnR,			// RIGHT (East) pushbutton
	input				btnCpuReset,	// CPU reset pushbutton
    input	[15:0]		sw,				// slide switches on Nexys 4
    
    
    // input	[3:0] 		JC,				// JC Pmod connector - debug signals
    //                                   // only the bottom row is used

    output	[15:0] 		led,			// LEDs on Nexys 4   
    output              RGB1_Blue,      // RGB1 LED (LD16) 
    output              RGB1_Green,
    output              RGB1_Red,
    output              RGB2_Blue,      // RGB2 LED (LD17)
    output              RGB2_Green,
    output              RGB2_Red,
    output [7:0]        an,             // Seven Segment display
    output [6:0]        seg,
    output              dp,
    
    input				uart_rtl_rxd,	// USB UART Rx and Tx on Nexys 4
    output				uart_rtl_txd,	
    
    output	[7:0] 		JA,				// JA Pmod connector - PmodCLP data bus
										// both rows are used
    output	[7:0] 		JB,				// JB Pmod connector - PmodCLP control signals
    
	output [7:0]		JC,							// only the bottom row is used
    //output	 		JC_out,				// JC Pmod connector - debug signals
										// only the bottom row is used
    //input           JC_in,
										
	input	[7:0]		JD				// JD Pmod connector - PmodENC signals
);

// internal variables
wire				sysclk;
wire				sysreset_n, sysreset;
wire				rotary_a, rotary_b, rotary_press, rotary_sw;
wire	[7:0]		lcd_d;
wire				lcd_rs, lcd_rw, lcd_e;

wire	[7:0]	gpio_in;				// embsys GPIO input port
wire	[7:0]	gpio_out;				// embsys GPIO output port
wire            pwm_out;                // PWM output from the axi_timer
////////////////////////////////////////////////////////////////////////////////
// signals to be used by our module
wire    [10:0]  lcd_out;
wire            mot_hall_a;
wire            mot_hall_b;
wire            mot_hall_c;
wire    [5:0]   mot_ctl_sig;
wire            div_clk;
////////////////////////////////////////////////////////////////////////////////
// signal assignments as required for the project
assign  lcd_d   = lcd_out[7:0];
assign  lcd_rs  = lcd_out[10];
assign  lcd_rw  = lcd_out[9];
assign  lcd_e   = lcd_out[8];
// taking inputs from JD
assign  JD[0]   = mot_hall_a;
assign  JD[1]   = mot_hall_b;
assign  JD[2]   = mot_hall_c;
// for JC
// motctl mappings
// motctl = {en3,in3,en2,in2,en1,in1}
//assign  JC[0]   = mot_ctl_sig[2];
//assign  JC[1]   = mot_ctl_sig[3];
//assign  JC[4]   = mot_ctl_sig[1];
//assign  JC[5]   = mot_ctl_sig[0];
//assign  JC[6]   = mot_ctl_sig[4];
//assign  JC[7]   = mot_ctl_sig[5];

// motctl = {en3,in3,en2,in2,en1,in1}
assign  JC[0]   = mot_ctl_sig[0];
assign  JC[1]   = mot_ctl_sig[1];
assign  JC[4]   = mot_ctl_sig[2];
assign  JC[5]   = mot_ctl_sig[3];
assign  JC[6]   = mot_ctl_sig[4];
assign  JC[7]   = mot_ctl_sig[5];
////////////////////////////////////////////////////////////////////////////////

// make the connections to the GPIO port.  Most of the bits are unused in the Getting
// Started project but GPIO's provide a convenient way to get the inputs and
// outputs from logic you create to and from the Microblaze.  For example,
// you may decide that using an axi_gpio peripheral is a good way to interface
// your hardware pulse-width detect logic with the Microblaze.  Our application
// is simple.

//wrap the pwm_out from the timer back to the application program for software pulse-width detect
assign gpio_in = {7	'b0000000, pwm_out};

//assigning the least significant bit of the gpio_out signal to the enable signal
//this would require some significant changes in the software
//assign enable_signal = gpio_channel_1_out[0];

// The FIT interrupt routine synthesizes a 20KHz signal and makes it
// available on GPIO2[0].  Bring it to the top level as an
// indicator that the system is running...could be handy for debug
wire            clk_20khz;
assign clk_20khz = gpio_out[0];

// We want to show the PWM output on LD15 (the leftmost LED;  The higher the PWM
// duty cycle, the brighter the LED but, the LEDs are controlled by the 
// Microblaze through Nexys4.  So, we have to play some games.  Instead of
// driving the leds directly, we will write 0 to led[15] and then OR in the PWM
// output. 
//wire    [15:0]  led_int;                // Nexys4IO drives these outputs
//assign led = led_int;  // LEDs are driven by led

// make the connections

// system-wide signals
assign sysclk = clk;
assign sysreset_n = btnCpuReset;		// The CPU reset pushbutton is asserted low.  The other pushbuttons are asserted high
										// but the microblaze for Nexys 4 expects reset to be asserted low
assign sysreset = ~sysreset_n;			// Generate a reset signal that is asserted high for any logic blocks expecting it.

// PmodCLP signals
// JA - top and bottom rows
// JB - bottom row only
assign JA = lcd_d[7:0];
assign JB = {1'b0, lcd_e, lcd_rw, lcd_rs, 2'b000, clk_20khz, pwm_out};

// PmodENC signals
// JD - bottom row only
// Pins are assigned such that turning the knob to the right
// causes the rotary count to increment.
assign rotary_a = JD[5];
assign rotary_b = JD[4];
assign rotary_press = JD[6];
assign rotary_sw = JD[7];

// Debug signals are on both rows of JC
//assign JC = {lcd_e, lcd_rs, lcd_rw, 1'b0, lcd_d[3:0]}; 
wire    freq_out;

//assign JC[2] = pwm_out;
//assign freq_out = JC[1];
//assign freq_out = JC_in;
//assign JC_out = pwm_out;

// btnC debounce
reg [3:0] btnc_val;
reg btnc_debounce_val;
always @(posedge sysclk) begin
    btnc_val <= {btnc_val[2:0],btnC}; 
end

always @(*) begin
    case(btnc_val)
        4'b0000 : btnc_debounce_val = 1'b0;
        4'b1111 : btnc_debounce_val = 1'b1;
        default : btnc_debounce_val = btnc_debounce_val;
    endcase
end

motor_driver #(
    .CLOCK_DIVIDER(32'd10_000_000)
) MD (
//    .sysclk(sysclk),
    .sysclk(btnc_debounce_val),
    .sysreset_n(sysreset_n),
    .direction(sw[14]),
    .enable(sw[15]),
    .motor_out(mot_ctl_sig),
    .div_clk(div_clk)
);

assign led = {sw[15:14], div_clk, btnC, 1'b0, btnc_val, 1'b0, mot_ctl_sig};
			
// instantiate the embedded system
/*
design_final_xil EMBSYS
       (//.PmodCLP_DataBus(lcd_d),
        //.PmodCLP_E(lcd_e),
        //.PmodCLP_RS(lcd_rs),
        //.PmodCLP_RW(lcd_rw),
        .PmodENC_A(rotary_a),
        .PmodENC_B(rotary_b),
        .PmodENC_BTN(rotary_press),
        .PmodENC_SWT(rotary_sw),
        //.RGB1_Blue(RGB1_Blue),
        //.RGB1_Green(RGB1_Green),
        //.RGB1_Red(RGB1_Red),
        //.RGB2_Blue(RGB2_Blue),
        //.RGB2_Green(RGB2_Green),
        //.RGB2_Red(RGB2_Red),
        //.an(an),
        //.btnC(btnC),
        //.btnD(btnD),
        //.btnL(btnL),
        //.btnR(btnR),
        //.btnU(btnU),
        //.dp(dp),
        .led_tri_o(led),
        //.seg(seg),
        .sw(sw),
        .btnCpuReset(btnCpuReset),
        .sysclk(sysclk),
        .uart_rtl_rxd(uart_rtl_rxd),
        .uart_rtl_txd(uart_rtl_txd),
        .lcd_tri_o(lcd_out),
        .Mot_Hall_A(mot_hall_a),
        .Mot_Hall_B(mot_hall_b),
        .Mot_Hall_C(mot_hall_c),
        .Mot_Ctl_Sig_tri_o(mot_ctl_sig)
        //.gpio_0_GPIO2_tri_o(gpio_out),
        //.gpio_0_GPIO_tri_i(gpio_in),
        //.pwm0(pwm_out),
        //.clk_out2(clk2),
        //.pwm_in(freq_out),
        //.gpio_0_GPIO_tri_o(gpio_channel_1_out)
        );
*/        
        
endmodule

